package com.stable.actor.core;

import lombok.extern.slf4j.Slf4j;

/**
 * 远程Actor引用 - 代表其他机器上的Actor
 * 适配单一端口设计
 */
@Slf4j
public class RemoteActorRef extends ActorRef {
    private final String host;
    private final int port;
    private final String remotePath;

    public RemoteActorRef(String host, int port, String path, ActorSystem actorSystem) {
        super(host + ":" + port + path, null, actorSystem, false);  // 远程Actor没有本地的StableActor实例
        this.host = host;
        this.port = port;
        this.remotePath = path;
    }

    @Override
    public void tell(Object message, ActorRef sender) {
        if (!isLocal()) {
            sendRemoteMessage(message, sender);
        } else {
            // 如果是本地，调用父类方法（理论上不会发生）
            log.warn("远程ActorRef被标记为本地，使用本地消息发送: {}", path());
            super.tell(message, sender);
        }
    }

    /**
     * 发送远程消息
     */
    private void sendRemoteMessage(Object message, ActorRef sender) {
        try {
            if (host == null || port <= 0) {
                throw new IllegalStateException("远程Actor引用缺少主机或端口信息: " + path());
            }

            // 使用ActorSystem的网络服务发送消息
            getActorSystem().sendRemoteMessage(host, port, remotePath, message, sender);

            log.debug("📤 发送远程消息到 {}:{} {}, 发送者: {}",
                    host, port, remotePath, sender != null ? sender.path() : "no-sender");

        } catch (Exception e) {
            log.error("❌ 发送远程消息失败: {}@{}:{}", remotePath, host, port, e);
            // 可以在这里处理重试逻辑或死信
            handleSendError(message, sender, e);
        }
    }

    /**
     * 处理发送错误
     */
    private void handleSendError(Object message, ActorRef sender, Exception error) {
        // 可以实现的错误处理策略：
        // 1. 重试机制
        // 2. 死信处理
        // 3. 错误回调
        log.warn("远程消息发送失败，消息可能丢失: {} -> {}@{}:{}",
                sender != null ? sender.path() : "no-sender",
                remotePath, host, port);

        // 如果是ask消息，需要通知等待的future
        if (message instanceof ActorRef.RemoteAskWrapper) {
            ActorRef.RemoteAskWrapper askWrapper = (ActorRef.RemoteAskWrapper) message;
            handleAskError(askWrapper.getCorrelationId(), error);
        }
    }

    /**
     * 处理ask消息发送错误
     */
    private void handleAskError(String correlationId, Exception error) {
        ActorRef.handleAskResponse(correlationId, new ActorRef.RemoteAskResponse(correlationId, error));
    }

    @Override
    public String path() {
        // 返回完整的远程路径格式：host:port/path
        return String.format("%s:%d%s", host, port, remotePath);
    }

    /**
     * 获取远程路径（不包含主机端口）
     */
    public String getRemotePath() {
        return remotePath;
    }

    /**
     * 获取完整网络地址
     */
    public String getNetworkAddress() {
        return host + ":" + port;
    }

    @Override
    public String toString() {
        return String.format("RemoteActorRef[%s:%d%s]", host, port, remotePath);
    }

    /**
     * 检查远程服务是否可用
     */
    public boolean isReachable() {
        // 简单的网络连通性检查
        try (java.net.Socket socket = new java.net.Socket(host, port)) {
            return socket.isConnected();
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 创建相同主机的其他Actor引用
     */
    public RemoteActorRef withPath(String newPath) {
        return new RemoteActorRef(host, port, newPath, getActorSystem());
    }

    /**
     * 比较两个远程引用是否指向同一主机
     */
    public boolean sameHost(RemoteActorRef other) {
        return this.host.equals(other.host) && this.port == other.port;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;

        RemoteActorRef that = (RemoteActorRef) obj;
        return port == that.port &&
                host.equals(that.host) &&
                remotePath.equals(that.remotePath);
    }

    @Override
    public int hashCode() {
        int result = host.hashCode();
        result = 31 * result + port;
        result = 31 * result + remotePath.hashCode();
        return result;
    }

    /**
     * 解析远程路径为RemoteActorRef
     */
    public static RemoteActorRef parse(String remotePath, ActorSystem actorSystem) {
        try {
            // 格式: host:port/actorPath 或 host:port/user/actorName
            String[] parts = remotePath.split("/", 2);
            String[] hostPort = parts[0].split(":");

            if (hostPort.length == 2 && parts.length == 2) {
                String host = hostPort[0];
                int port = Integer.parseInt(hostPort[1]);
                String path = "/" + parts[1];
                return new RemoteActorRef(host, port, path, actorSystem);
            }
        } catch (Exception e) {
            log.error("解析远程路径失败: {}", remotePath, e);
        }
        return null;
    }

    /**
     * 创建系统管理相关的远程引用
     */
    public static RemoteActorRef forSystemService(String host, int port, String serviceName, ActorSystem actorSystem) {
        String path = "/user/" + serviceName;
        return new RemoteActorRef(host, port, path, actorSystem);
    }

    /**
     * 创建Worker到Master的远程引用
     */
    public static RemoteActorRef forMasterService(String masterHost, String serviceName, ActorSystem actorSystem) {
        return forSystemService(masterHost, 2551, serviceName, actorSystem);
    }

    /**
     * 创建Master到Worker的远程引用
     */
    public static RemoteActorRef forWorkerService(String workerHost, String serviceName, ActorSystem actorSystem) {
        return forSystemService(workerHost, 2552, serviceName, actorSystem);
    }
}
